/********************************************************************************
						2024/9/28	Created by S.W. Tang
 ********************************************************************************/
#include "TSystem.h"
#include "TGeoManager.h"
#include "TGeoVolume.h"
#include "TGeoMaterial.h"
#include "TGeoMedium.h"
#include "TGeoPgon.h"
#include "TGeoXtru.h"
#include "TGeoMatrix.h"
#include "TGeoCompositeShape.h"
#include "TFile.h"
#include "TString.h"
#include "TList.h"
#include "TROOT.h"



#include <iostream>

using namespace TMath;
const double cm = 1.;
const double mm = 0.1*cm;
const double um = 0.001*mm;
const double pi = TMath::Pi();
const double deg = pi/180;

//// MUSIC construction parameters
//  outer Al shell with two Mylar windows
const double MUSIC_outer_width = 280*mm;
const double MUSIC_outer_height =202*mm;
const double MUSIC_outer_length= 430*mm;
const double MUSIC_outer_thickness = 16*mm;
const double MUSIC_outer_window_sizeXY = 100*mm;
const double MUSIC_outer_window_thick = 10*um;

///// MUSIC field cage, PCB construction
const double FieldCage_AC_width = 186*mm;         /// Anode and cathode
const double FieldCage_AC_length = 173*mm;
const double FieldCage_AC_thickness = 3*mm;
const double FieldCage_G_width = 127*mm;          // Grid
const double FieldCage_G_length = 173*mm;
const double FieldCage_G_thickness = 6*mm;
const double FieldCage_G_holeX = 110*mm;
const double FieldCage_G_holeZ = 155*mm;
const double FieldCage_wire_radius = 37.5*um;
const double FieldCage_wire_space = 0.75*mm;     /// wire spacing in grid plane

const double FieldCage_GRF_width = 147*mm;              /// Grading Ring Front
const double FieldCage_GRF_height = 119*mm;
const double FieldCage_GRF_thickness = 3*mm;
const double FieldCage_GRF_windowXY = 95*mm;
const double FieldCage_GRS_width = 173*mm;              /// Grading Ring side
const double FieldCage_GRS_height = 100*mm;
const double FieldCage_GRS_thickness = 2*mm;

double sensitive_gas_X = 100*mm;
double sensitive_gas_Y = FieldCage_GRS_height;
double sensitive_gas_Z = 36*mm;
double sensitive_gas_gapZ = 0.2*mm;
// double sensitive_gas_gapZ = 0.0;
double field_electrode_Z =14*mm;

/// placement of the FieldCage
const double FieldCage_gapZ = 2*cm;
double FieldCage_Cathode_Y  = (sensitive_gas_Y+FieldCage_AC_thickness)/2.;
double FieldCage_Grid_Y  = -(sensitive_gas_Y+FieldCage_G_thickness)/2.;
double FieldCage_Anode_Y  = -(sensitive_gas_Y+FieldCage_AC_thickness+2*FieldCage_G_thickness)/2.;
//// placement of the MUSIC
const double MUSIC_posX = 0;
const double MUSIC_posY = 0;
const double MUSIC_posZ = 50*cm;




// Name of geometry version and output file
TString geoPath = gSystem->Getenv("VMCWORKDIR");

const TString geoVersion = "music_F6_v0";

const TString FileName = geoPath + "/geometry/" + geoVersion + ".root";
// const TString FileName1 = geoPath + "/geometry/" + geoVersion + "_geomanager.root";

// Names of the different used materials which are used to build the modules
// The materials are defined in the global media.geo file
const TString MUSICVolumeMedium  = "P10";
const TString MUSIC_foil_str    = "mylar";
const TString Aluminum_str      = "Aluminum";
const TString PCB_str           = "pcbmvd";
const TString wire_str           = "copper";



// some global variables
TGeoManager* gGeoMan = NULL;  // Pointer to TGeoManager instance

// Forward declarations
void create_materials_from_media_file();

void Create_Music_F6_v0(){
	// std::cout<<"FieldCage_Grid_Y:"<<FieldCage_Grid_Y<<std::endl;
	create_materials_from_media_file();
	
	gGeoMan=(TGeoManager*)gROOT->FindObject("FAIRGeom");
	gGeoMan->SetName("MUSICgeom");
	gGeoMan->SetVisLevel(7);

	TGeoVolume* topMUSIC = new TGeoVolumeAssembly("TOPMUSIC");
	gGeoMan->SetTopVolume(topMUSIC);

	/******  MUSIC construction  ******/
	TGeoVolume* music = new TGeoVolumeAssembly(geoVersion);
		
	TGeoMedium* med_gas = gGeoMan->GetMedium(MUSICVolumeMedium);
	TGeoMedium* med_foil = gGeoMan->GetMedium(MUSIC_foil_str);  //前后foil的材料
	TGeoMedium* med_Al = gGeoMan->GetMedium(Aluminum_str);
	TGeoMedium* med_pcb = gGeoMan->GetMedium(PCB_str);
	TGeoMedium* med_copper = gGeoMan->GetMedium(wire_str);
	
	
	TGeoRotation *zeroRotation = new TGeoRotation();
	zeroRotation->RotateX(0.);
	zeroRotation->RotateY(0.);
	zeroRotation->RotateZ(0.);
	TGeoCombiTrans* zero_CombiTrans = new TGeoCombiTrans(0, 0, 0, zeroRotation);
	
	////// Aluminum shell definition
	TGeoBBox* Al_box0 = new TGeoBBox("Al_box0", MUSIC_outer_width/2, MUSIC_outer_height/2, MUSIC_outer_length/2);
	TGeoBBox* Al_box1 = new TGeoBBox("Al_box1", MUSIC_outer_width/2-MUSIC_outer_thickness, MUSIC_outer_height/2-MUSIC_outer_thickness, MUSIC_outer_length/2-MUSIC_outer_thickness);
	TGeoBBox* Al_box2 = new TGeoBBox("Al_box2", MUSIC_outer_window_sizeXY/2, MUSIC_outer_window_sizeXY/2, MUSIC_outer_length/2);
	TGeoCompositeShape *Al_shape0 = new TGeoCompositeShape("Al_shape0","Al_box0-Al_box1");
	TGeoCompositeShape *MUSIC_Al_shape = new TGeoCompositeShape("MUSIC_Al_shape","Al_shape0-Al_box2");
	TGeoVolume *MUSIC_Al_vol = new TGeoVolume("MUSIC_Al_vol", MUSIC_Al_shape, med_Al);
	MUSIC_Al_vol->SetLineColor(kGray);
	MUSIC_Al_vol->SetVisLeaves(kTRUE);
	music->AddNode(MUSIC_Al_vol, 1, zero_CombiTrans);

	//// entrance window, mylar foil
	TGeoBBox* foil_box = new TGeoBBox("foil_box", MUSIC_outer_window_sizeXY/2, MUSIC_outer_window_sizeXY/2, MUSIC_outer_window_thick/2);
	TGeoVolume *MUSIC_foil_vol = new TGeoVolume("MUSIC_foil_vol", foil_box, med_foil);
	MUSIC_foil_vol->SetLineColor(kGreen);
	Double_t foil_z1 = MUSIC_outer_length/2-MUSIC_outer_thickness+MUSIC_outer_window_thick/2;
	Double_t foil_z2 = - foil_z1;
	TGeoCombiTrans* foil1_combtrans = new TGeoCombiTrans(0, 0, foil_z1, zeroRotation);
	TGeoCombiTrans* foil2_combtrans = new TGeoCombiTrans(0, 0, foil_z2, zeroRotation);
	// cout<<foil_z1/mm<<"mm,  "<<foil_z2/mm<<"mm,  "<<endl;
	music->AddNode(MUSIC_foil_vol, 1, foil1_combtrans);
	music->AddNode(MUSIC_foil_vol, 2, foil2_combtrans);
	///// gas region definition
	TGeoBBox* gas_box = new TGeoBBox("gas_box", MUSIC_outer_width/2-MUSIC_outer_thickness, MUSIC_outer_height/2-MUSIC_outer_thickness, MUSIC_outer_length/2-MUSIC_outer_thickness);
	// cout<<"X = "<<MUSIC_outer_width/2-MUSIC_outer_thickness<<endl;
	// cout<<"Y = "<<MUSIC_outer_height/2-MUSIC_outer_thickness<<endl;
	// cout<<"Z = "<<MUSIC_outer_length/2-MUSIC_outer_thickness<<endl;
	TGeoVolume *MUSIC_gas_vol = new TGeoVolume("MUSIC_gas_vol", gas_box, med_gas);
	MUSIC_gas_vol->SetVisLeaves(kFALSE);
	music->AddNode(MUSIC_gas_vol, 1,zero_CombiTrans);

	//// PCB, field cage definition
	TGeoBBox* sensitive_box = new TGeoBBox("sensitive_box", sensitive_gas_X/2, sensitive_gas_Y/2,sensitive_gas_Z/2);
	TGeoVolume *MUSIC_sensitive_vol = new TGeoVolume("MUSICF6_sensitive_vol", sensitive_box, med_gas);
	MUSIC_sensitive_vol->SetLineColor(kMagenta);
	MUSIC_sensitive_vol->SetVisLeaves(kTRUE);
	double posZ_sensitive1 = -FieldCage_gapZ/2-sensitive_gas_gapZ-field_electrode_Z - sensitive_gas_Z/2;
	double dZ_sensitive = sensitive_gas_Z+sensitive_gas_gapZ;
	for(Int_t i=0;i<4;i++){   ///// place 8 sensitive volume, the copy number is 1 - 8 along Z axis
		double posZ =  posZ_sensitive1-(3-i)*dZ_sensitive;
		TGeoCombiTrans* CombiTrans0 = new TGeoCombiTrans(0, 0, posZ, zeroRotation);
		MUSIC_gas_vol->AddNode(MUSIC_sensitive_vol, i+1, CombiTrans0);
		TGeoCombiTrans* CombiTrans1 = new TGeoCombiTrans(0, 0, -posZ, zeroRotation);
		MUSIC_gas_vol->AddNode(MUSIC_sensitive_vol, 8-i, CombiTrans1);
		// cout<<"sensitive_posZ"<<i+1<<": "<<posZ/mm<<" mm"<<endl;
		// cout<<"edge of ssensitive: "<<MUSIC_posZ + posZ - sensitive_gas_Z/2<<" cm"<<endl;
		// cout<<"edge of ssensitive: "<<MUSIC_posZ + posZ + sensitive_gas_Z/2<<" cm"<<endl;
		// cout<<"edge of ssensitive: "<<MUSIC_posZ - posZ - sensitive_gas_Z/2<<" cm"<<endl;
		// cout<<"edge of ssensitive: "<<MUSIC_posZ - posZ + sensitive_gas_Z/2<<" cm"<<endl;
	}
	/// cathode and anode
	TGeoBBox* FieldCage_AC_box = new TGeoBBox("FieldCage_AC_box", FieldCage_AC_width/2, FieldCage_AC_thickness/2,FieldCage_AC_length/2); /// cathode and anode
	TGeoVolume* FieldCage_AC_vol = new TGeoVolume("FieldCage_AC_vol", FieldCage_AC_box, med_pcb);
	double posZ = -(FieldCage_gapZ/2 + FieldCage_AC_length/2);
	TGeoCombiTrans* trans0 = new TGeoCombiTrans(0, FieldCage_Cathode_Y, posZ, zeroRotation);
	TGeoCombiTrans* trans1 = new TGeoCombiTrans(0, FieldCage_Anode_Y, posZ, zeroRotation);
	// cout<<"FieldCage_Anode_Y="<<FieldCage_Anode_Y<<endl;
	TGeoCombiTrans* trans2 = new TGeoCombiTrans(0, -FieldCage_Cathode_Y, -posZ, zeroRotation);
	TGeoCombiTrans* trans3 = new TGeoCombiTrans(0, -FieldCage_Anode_Y, -posZ, zeroRotation);
	MUSIC_gas_vol->AddNode(FieldCage_AC_vol, 1, trans0); /// place cathode of field cage 1
	MUSIC_gas_vol->AddNode(FieldCage_AC_vol, 2, trans1); /// place anode of field cage 1
	MUSIC_gas_vol->AddNode(FieldCage_AC_vol, 3, trans2); /// place cathode of cage 2
	MUSIC_gas_vol->AddNode(FieldCage_AC_vol, 4, trans3); /// place anode of field cage 2

	////grid plane
	TGeoBBox* FieldCage_grid_box = new TGeoBBox("FieldCage_grid_box", FieldCage_AC_length/2, FieldCage_wire_radius, FieldCage_AC_width/2); /// grid
	TGeoVolume* FieldCage_grid_vol = new TGeoVolume("FieldCage_grid_vol", FieldCage_grid_box, med_gas);
	TGeoTube* wire_tube = new TGeoTube("wire_tube", 0, FieldCage_wire_radius, FieldCage_AC_width/2);
	TGeoVolume* Gridwire_vol = new TGeoVolume("Gridwire_vol", wire_tube, med_copper);
	Gridwire_vol->SetLineColor(kRed);
	Gridwire_vol->SetVisLeaves(kTRUE);
	double posx_wire0 = - FieldCage_AC_length/2 + 5*mm;
	Int_t Nwires = (FieldCage_AC_length- 10*mm)/FieldCage_wire_space;
	for (Int_t i = 0; i < Nwires; i++)
	{
		TGeoCombiTrans* trans = new TGeoCombiTrans(posx_wire0+FieldCage_wire_space*i,0,0,zeroRotation);
		FieldCage_grid_vol->AddNode(Gridwire_vol, i+1, trans);       // place grid wires
	}
	// Rotation: 
	TGeoRotation *gRot = new TGeoRotation();
	gRot->RotateX(0.);
	gRot->RotateY(90.0);
	gRot->RotateZ(0.);

	TGeoCombiTrans* trans_grid1 = new TGeoCombiTrans(0, FieldCage_Grid_Y, posZ, gRot);
	TGeoCombiTrans* trans_grid2 = new TGeoCombiTrans(0, -FieldCage_Grid_Y, -posZ, gRot);
	MUSIC_gas_vol->AddNode(FieldCage_grid_vol, 1, trans_grid1);        //// place grid1
	MUSIC_gas_vol->AddNode(FieldCage_grid_vol, 2, trans_grid2);       //// place grid2
	// cout<<"FieldCage_Grid_Y="<<FieldCage_Grid_Y<<endl;

	TGeoCombiTrans* ptrans = new TGeoCombiTrans(MUSIC_posX, MUSIC_posY, MUSIC_posZ, zeroRotation);  // place MUSIC
	topMUSIC->AddNode(music, 1, ptrans);
	cout<<"Voxelizing."<<endl;
	topMUSIC->Voxelize("");
	gGeoMan->CloseGeometry();

	
	TView *view = TView::CreateView(); // 创建3D视图
	topMUSIC->Draw();
	view->ShowAxis();
	
	gGeoMan->CheckOverlaps(0.001);
	gGeoMan->PrintOverlaps();
	gGeoMan->Test();

	TFile* outfile = TFile::Open(FileName,"RECREATE");
	topMUSIC->Write();
	outfile->Close();

	// TFile* outfile1 = TFile::Open(FileName1,"RECREATE");
	// gGeoMan->Write();
	// outfile1->Close();

	// cout<<topMUSIC->GetNumber()<<endl;
	// cout<<music->GetNumber()<<endl;
	// cout<<MUSIC_Al_vol->GetNumber()<<endl;
	// cout<<MUSIC_foil_vol->GetNumber()<<endl;
	// cout<<MUSIC_gas_vol->GetNumber()<<endl;
	// cout<<MUSIC_sensitive_vol->GetNumber()<<endl;
	// cout<<FieldCage_AC_vol->GetNumber()<<endl;
	// cout<<FieldCage_grid_vol->GetNumber()<<endl;
	// cout<<Gridwire_vol->GetNumber()<<endl;

}

void create_materials_from_media_file()
{
    // Use the FairRoot geometry interface to load the media which are already defined
    FairGeoLoader* geoLoad = new FairGeoLoader("TGeo", "FairGeoLoader");
    FairGeoInterface* geoFace = geoLoad->getGeoInterface();
    //TString geoPath = gSystem->Getenv("VMCWORKDIR");
    TString geoFile = geoPath + "/geometry/media_hiribl.geo";
    cout<<"geoFile is "<<geoFile<<endl;
    geoFace->setMediaFile(geoFile);
    geoFace->readMedia();
    // Read the required media and create them in the GeoManager
    FairGeoMedia* geoMedia = geoFace->getMedia();
    FairGeoBuilder* geoBuild = geoLoad->getGeoBuilder();
    FairGeoMedium* air = geoMedia->getMedium("air");
    FairGeoMedium* copper = geoMedia->getMedium("copper");
    FairGeoMedium* MUSICmixture = geoMedia->getMedium("P10");
    FairGeoMedium* Mylar = geoMedia->getMedium("mylar");
    FairGeoMedium* Aluminum = geoMedia->getMedium("Aluminum");
    FairGeoMedium* PCB = geoMedia->getMedium("pcbmvd");
    // include check if all media are found 
    geoBuild->createMedium(air);
    geoBuild->createMedium(copper);
    geoBuild->createMedium(MUSICmixture);
    geoBuild->createMedium(Mylar);
    geoBuild->createMedium(Aluminum);
    geoBuild->createMedium(PCB);
}


